package com.finance.util.xml;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.sql.Wrapper;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

/**
 * Jaxb2工具类
 * @author   gyw
 * @create   2017-4-21 下午2:40:14
 */
public class JaxbUtil {
    protected static final Logger logger = LoggerFactory.getLogger(JaxbUtil.class);

    public static String stripNonValidXMLCharacters(String in) {
        StringBuffer out = new StringBuffer(); // Used to hold the output.
        char current; // Used to reference the current character.

        if (in == null || ("".equals(in))) {
            return ""; // vacancy test.
        }
        for (int i = 0; i < in.length(); i++) {
            current = in.charAt(i); // NOTE: No IndexOutOfBoundsException caught here; it should not happen.
            if ((current == 0x9) ||
                    (current == 0xA) ||
                    (current == 0xD) ||
                    ((current >= 0x20) && (current <= 0xD7FF)) ||
                    ((current >= 0xE000) && (current <= 0xFFFD)) ||
                    ((current >= 0x10000) && (current <= 0x10FFFF))) {
                out.append(current);
            }
        }
        return out.toString();
    }
    /**
     * JavaBean转换成xml(不带头部申明)
     * @param c
     * @param <T>
     * @return
     */
    public static <T extends Object> String bean2xml(T c) {
        Marshaller marshaller = null;
        StringWriter writer = new StringWriter();
        try {
            JAXBContext context = JAXBContext.newInstance(c.getClass());
            marshaller = context.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");//编码格式
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false);//是否格式化生成的xml串
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);//是否省略xml头信息
            marshaller.marshal(c, writer);
        } catch (JAXBException e) {
            logger.error(e.getMessage(),e);
        }
        return writer.toString();
    }

    /**
     * JavaBean转换成xml(带头部申明)
     * 默认编码UTF-8
     * @param obj
     * @return
     */
    public static String convertToXml(Object obj) {
        return convertToXml(obj, "UTF-8");
    }

    /**
     * JavaBean转换成xml(带头部申明)
     * @param obj
     * @param encoding
     * @return
     */
    public static String convertToXml(Object obj, String encoding) {
        String result = null;
        try {
            JAXBContext context = JAXBContext.newInstance(obj.getClass());
            Marshaller marshaller = context.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);

            StringWriter writer = new StringWriter();
            marshaller.marshal(obj, writer);
            result = writer.toString();
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
        }

        return result;
    }

    /**
     * xml转换成JavaBean
     * @param xml
     * @param c
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T converyToJavaBean(String xml, Class<T> c) {
        T t = null;
        try {
            JAXBContext context = JAXBContext.newInstance(c);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            t = (T) unmarshaller.unmarshal(new StringReader(stripNonValidXMLCharacters(xml)));
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            logger.error("xml转换bean错误，原文：{}，bean:{}",xml,c.getCanonicalName());
        }
        return t;
    }

    /**
     * xml转换成JavaBean List
     * @param clazz
     * @param dataStream
     * @param <T>
     * @return
     * @throws JAXBException
     */
    public static <T> T readConfigFromStream(Class<T> clazz, InputStream dataStream) throws JAXBException {
        try {
            JAXBContext jc = JAXBContext.newInstance(clazz);
            Unmarshaller u = jc.createUnmarshaller();
            return (T) u.unmarshal(dataStream);
        } catch (JAXBException e) {
            throw e;
        }
    }

}
